#ifndef _SOCKET_MANAGER_HPP_20120424
#define _SOCKET_MANAGER_HPP_20120424

#include <ext/hash_map>
#include <vector>

#ifdef _MULTIPLE_THREAD
#include "lock.hpp"
#endif

#include "waker.hpp"

#include "base.hpp"
#include "circle_array.hpp"
#include "object_pool.hpp"
#include "memory_pool.hpp"

#include "simple_epoll.hpp"
#include "net_addr.hpp"
#include "sock_comm.hpp"

namespace mina
{
	class Connection;
	class AbstractParser;
	class AbstractProcessor;

	class SocketManager
	{
		public :
#ifdef _USE_VECTOR
			typedef typename std::vector<Connection*> ConnMap;
#else
			typedef typename __gnu_cxx::hash_map<uint64_t, Connection*> ConnMap;
#endif
			typedef typename ConnMap::iterator ConnMap_Iter;
			typedef typename ConnMap::const_iterator ConnMap_CIter;

			typedef ObjectPool<Connection> ConnPool;

			typedef CircleArray<Connection*> ConnCircleArray;

		public :
			SocketManager(
# ifdef _MULTIPLE_THREAD
					BufferAlloc & wr_alloc, BufferAlloc & rd_alloc,
# else
						BufferAlloc & alloc,
#endif
					int max_conn, long epoll_timeout = 0);

			virtual ~SocketManager();

			virtual int poll(SocketManager * pMgr = NULL);

			int send_data(const ConnID & connid, void * data);

			void process_message();

		public :
			virtual int accept(Connection & conn) { return 0; }

			Connection * alloc_conn(const ConnID & connid, int fd, const NetAddr & addr, \
										AbstractParser & parser, AbstractProcessor & processor);

			void dealloc_conn(Connection & conn);
			void close_conn(Connection & conn, int err = - E_CONNECT_CLOSE, int state = E_RELEASE_STATE);

			void push_rd_active_queue(Connection & conn);
			Connection * pop_rd_active_queue();
			void push_wr_active_queue(Connection & conn);
			Connection * pop_wr_active_queue();

			uint64_t     next_id() { return ++ _conn_id; }

		public :
			void wake()    {   _waker.wake(_simple_epoll);   }
			void wakeup()  {   _waker.wakeup(_simple_epoll); }

		public :
			long                 _epoll_timeout;

			SimpleEpoll          _simple_epoll;
			
			ConnPool             _conn_pool;
			
			ConnMap              _conn_map;

			ConnCircleArray      _rd_active_queue;
			ConnCircleArray      _wr_active_queue;

			Waker                _waker;
			
			DECL_LOGGER(logger);
# ifdef _MULTIPLE_THREAD
			BufferAlloc &        _wr_alloc;
			BufferAlloc &        _rd_alloc;

			/// protect read active queue
			thread::Lock         _rd_active_lock;
			/// protect write active queue
			thread::Lock         _wr_active_lock;
# else
			BufferAlloc &        _alloc;
# endif	

		private :
			uint64_t             _conn_id;
	};
}

#endif

